<?php

namespace app\admin\controller;

use api\geetest\GeetestLib;
use Predis\Client;
use think\cache\driver\Redis;
use think\Controller;
use think\Cookie;
use think\Request;
use app\admin\validate;
use app\admin\model\Admin;
use think\Session;

class Login extends Controller
{
    /**
     * 跳转登录页面
     *
     * @return \think\Response
     */
    public function login()
    {
        return view('login/login');
    }

    public function dologin()
    {
        // 判断是不是post传输
        if (request()->isPost()) {

            $redis = new Client();

            // 获取用户ip
            $ip = Request::instance()->ip();

            // 将ip转化成字串
            $strIp = ip2long($ip);

            // 获取2小时内锁定的次数
            $lock = $redis->get('admin:status:'.$strIp);

            // 判断状态码存不存在
            if (!empty($redis->get('admin:status:' . $strIp))) {
                $this->error('信息不正确,为了保证账户安全，系统已经将您账号锁定'.(1 * $lock*$lock).'分钟');
            }

            // 接受前端数据
            $data = [
                'name' => input('name'),
                'pwd' => input('pwd'),
            ];

            // 验证数据
            $validate = validate('Login');
            if (!$validate->check($data)) {
                return $this->error($validate->getError());
            }

            // 获取redis数据
            $id = $redis->get('admin:name:' . $data['name'] . ':id');

            // 验证 redis中数据
            if (!empty($id)) {

                $pwd = $redis->hget('admin:'.$id, 'pwd');

                if ($pwd == MD5($data['pwd'])) {
                    session('admin_name', $data['name']);

                    $this->success('登录成功', 'admin/index/index');
                } else {
                    // 获取用户ip
                    $ip = Request::instance()->ip();
                    // 将ip转化成字串
                    $strIp = ip2long($ip);
                    // 调用错误记录 查看用户2小时共错了多少次
                    if ($this->err($strIp)) {
                        // 获取错误次数
                        $errNum = $redis->get('admin:'.$strIp);

                        $this->error('用户名或密码错误,再输入'.(5-$errNum).'将被锁定');
                    }
                }
            } else {

                //  redis 中不存在数据去请求数据库
                $admin = model('admin');
                $res = $admin->login($data);

                // 数据库没有用户信息
                if (!$res) {
                    // 获取用户ip
                    $ip = Request::instance()->ip();
                    // 将ip转化成字串
                    $strIp = ip2long($ip);
                    // 调用错误记录 查看用户2小时共错了多少次
                    if ($this->err($strIp)) {
                        // 获取错误次数
                        $errNum = $redis->get('admin:'.$strIp);

                        $this->error('用户名或密码错误,再输入'.(5-$errNum).'将被锁定');
                    }

                } else {
                    // 数据有用户信息
                    $list = [
                        'login_ip' => $ip,
                        'login_time' => time(),
                        'times' => ++$res['times'],
                    ];

                    // 更新数据库
                    $dotime = model('admin');
                    $dotime->dologin($list,$res['id']);

                    // 设置自增id
                    $id = $redis->incr('admin:id');

                    // 将用户名存入redis有效期为2小时
//                    $redis->setex('admin:'.$data['name'], '7200', $data['name']);

//                    var_dump($data['name']);die;
                    // 将用户名存进session中
                    session('admin_name', $data['name']);

                    // 将用户ID存入redis
                    $redis->setex('admin:name:' . $data['name'] . ':id','7200', $id);

                    // 将用户信息以自增 id 存入redis(hash)
                    $redis->hset('admin:'.$id, 'pwd', MD5($data['pwd']));

                    $this->success('登录成功', 'admin/index/index');
                }
            }

        } else { // 不是post传输的数据报错
            $this->error('你是不是走错了');
        }
    }

    /**
     * @param $ip 用户ip
     * @return bool
     */
    public function err($ip)
    {
        $redis = new Client();

        // 判断用户ip是不是2小时内第一次错误
        if (empty($redis->get('admin:'.$ip))) {
            // 清楚之前的数据
            $redis->del('admin.LockNum:'.$ip);

            $redis->setex('admin.num:'.$ip, 7200, 1);
            // 将错误次数存入redis中,有效时间2小时
            $redis->setex('admin:'.$ip, 7200, 1);
            return true;

            // 判断当前ip用户的错误次数小于4次
        } else if ($redis->get('admin:'.$ip) < 4) {
            // 自增num
            $redis->incr('admin.num:'.$ip);
            // 将用户的错误次数存进redis中 存入第一次剩余时间
            $redis->setex('admin:'.$ip, 7200, $redis->get('admin.num:'.$ip));
            return true;
        } else {
            // 当用户ip错误次数大于5次时禁用

            // 判断 2小时内是不是第一次锁定 不是自增1
            empty($redis->get('admin:LockNum:'.$ip))? $redis->setnx('admin:LockNum:'.$ip, 1): $redis->incr('admin:LockNum:'.$ip);

            $num = $redis->get('admin:LockNum:'.$ip);

            // 设置有效期, 用户错误次数记录
            $redis->setex('admin:status:' . $ip, (60*$num*$num), $num);

            $this->error('信息不正确,为了保证账户安全，系统已经将您账号锁定'. (1 * $num*$num).'分钟');
        }
    }

    public function req()
    {
        /**
         * 使用Get的方式返回：challenge和capthca_id 此方式以实现前后端完全分离的开发模式 专门实现failback
         * @author Tanxu
         */

        $myid = '2d66c1f80de3fea77867520d5780c3e4';
        $mykey = '4e9a757f6d1d1ea01928c7d5cdc83d0d';

        $GtSdk = new GeetestLib($myid, $mykey);

        $data = array(
            "user_id" => "2d66c1f80de3fea77867520d5780c3e4", # 网站用户id
            "client_type" => "web", #web:电脑上的浏览器；h5:手机上的浏览器，包括移动应用内完全内置的web_view；native：通过原生SDK植入APP应用的方式
            "ip_address" => "127.0.0.1" # 请在此处传输用户请求验证时所携带的IP
        );

        $status = $GtSdk->pre_process($data, 1);
        Session::get('gtserver', $status);
        Session::get('user_id', $data['user_id']);
        return $GtSdk->get_response_str();
    }

}
